#include "stdafx.h"
#include "PhysicsEngine.h"
/*
// Needed to include these in the .cpp-file, otherwise it refused to work
// Keycode
#define HK_CLASSES_FILE <Common/Serialize/Classlist/hkClasses.h>  
#include <Common/Base/keycode.cxx>
#include <Common/Base/Config/hkProductFeatures.cxx>

PhysicsEngine *PhysicsEngine::instance = 0;

PhysicsEngine *PhysicsEngine::getInstance() {
	if (!instance) {
		instance = new PhysicsEngine();
	}

	return instance;
}

PhysicsEngine::PhysicsEngine() {
	initialize();

	m_context = NULL;
	m_vdb = NULL;
}

PhysicsEngine::~PhysicsEngine() {
	//TODO delete stuff
	shutdown();
}

hkJobQueue* PhysicsEngine::getJobQueue() {
	return m_jobQueue;
}

void PhysicsEngine::platformInit() {
	// When deploying Havok via the Intel ADP platform, it is necessary to
	// initialize the ADP server and authorize the application using the
	// API calls below. For regular usage, these can be ignored.
	#if defined( HK_ATOM )
		if ( ADP_Initialize() != 0 )
		{
			printf( "Could not initialize ADP licensing system.\n" );
			exit(1);
		}
		if ( ADP_IsAuthorized( applicationID ) != 5 )
		{
			printf( "ADP application could not be authorized.\n" );
			exit(1);
		}
	#endif
}

void PhysicsEngine::platformQuit() {
	#if defined( HK_ATOM )
		ADP_Close();
	#endif
}

static void HK_CALL errorReport(const char* msg, void* userArgGivenToInit) {
	PRINTF("%s", msg);
}

void PhysicsEngine::initialize() {
	//
	// Do platform specific initialization
	//
	platformInit();

	//
	// Initialize the base system including our memory system
	//
	// Allocate 0.5MB of physics solver buffer.
	hkMemoryRouter* memoryRouter = hkMemoryInitUtil::initDefault( hkMallocAllocator::m_defaultMallocAllocator, hkMemorySystem::FrameInfo( 500* 1024 ) );
	hkBaseSystem::init( memoryRouter, errorReport );
	
	//
	// Initialize the multi-threading classes, hkJobQueue, and hkJobThreadPool
	//

	// They can be used for all Havok multithreading tasks. In this exmaple we only show how to use
	// them for physics, but you can reference other multithreading demos in the demo framework
	// to see how to multithread other products. The model of usage is the same as for physics.
	// The hkThreadpool has a specified number of threads that can run Havok jobs.  These can work
	// alongside the main thread to perform any Havok multi-threadable computations.
	// The model for running Havok tasks in Spus and in auxilary threads is identical.  It is encapsulated in the
	// class hkJobThreadPool.  On PlayStation(R)3 we initialize the SPU version of this class, which is simply a SPURS taskset.
	// On other multi-threaded platforms we initialize the CPU version of this class, hkCpuJobThreadPool, which creates a pool of threads
	// that run in exactly the same way.  On the PlayStation(R)3 we could also create a hkCpuJobThreadPool.  However, it is only
	// necessary (and advisable) to use one Havok PPU thread for maximum efficiency. In this case we simply use this main thread
	// for this purpose, and so do not create a hkCpuJobThreadPool.
		

	// We can cap the number of threads used - here we use the maximum for whatever multithreaded platform we are running on. This variable is
	// set in the following code sections.
	int totalNumThreadsUsed;

	#if defined HK_PLATFORM_PS3_PPU

		hkSpuJobThreadPoolCinfo threadPoolCinfo;

		extern CellSpurs* initSpurs();
		HK_CELL_SPURS* spurs = initSpurs();

		hkSpuUtil* spuUtil = new hkSpuUtil( spurs );

		threadPoolCinfo.m_spuUtil = spuUtil;
		threadPoolCinfo.m_maxNumSpus = 5; // Use 5 SPUs for this example

		totalNumThreadsUsed = 1; // only use one CPU thread for PS3.

		// This line enables timers collection, by allocating 200 Kb per thread.  If you leave this at its default (0),
		// timer collection will not be enabled.
		threadPoolCinfo.m_perSpuMonitorBufferSize = 200000;
		threadPool = new hkSpuJobThreadPool( threadPoolCinfo );
		spuUtil->removeReference();

	#else

		// Get the number of physical threads available on the system
		hkHardwareInfo hwInfo;
		hkGetHardwareInfo(hwInfo);
		totalNumThreadsUsed = hwInfo.m_numThreads;

		// We use one less than this for our thread pool, because we must also use this thread for our simulation
		hkCpuJobThreadPoolCinfo threadPoolCinfo;
		threadPoolCinfo.m_numThreads = totalNumThreadsUsed - 1;

		// This line enables timers collection, by allocating 200 Kb per thread.  If you leave this at its default (0),
		// timer collection will not be enabled.
		threadPoolCinfo.m_timerBufferPerThreadAllocation = 200000;
		m_threadPool = new hkCpuJobThreadPool( threadPoolCinfo );

	#endif

	// We also need to create a Job queue. This job queue will be used by all Havok modules to run multithreaded work.
	// Here we only use it for physics.
	hkJobQueueCinfo info;
	info.m_jobQueueHwSetup.m_numCpuThreads = totalNumThreadsUsed;
	m_jobQueue = new hkJobQueue(info);

	//
	// Enable monitors for this thread.
	//

	// Monitors have been enabled for thread pool threads already (see above comment).
	hkMonitorStream::getInstance().resize(200000);
}

hkJobThreadPool* PhysicsEngine::getThreadPool() {
	return m_threadPool;
}

void PhysicsEngine::setupVisualDebugger(hkpWorld* world) {
	world->markForWrite();

	//
	// Initialize the VDB
	//
	
	// <PHYSICS-ONLY>: Register physics specific visual debugger processes
	// By default the VDB will show debug points and lines, however some products such as physics and cloth have additional viewers
	// that can show geometries etc and can be enabled and disabled by the VDB app.
	
	{
		// The visual debugger so we can connect remotely to the simulation
		// The context must exist beyond the use of the VDB instance, and you can make
		// whatever contexts you like for your own viewer types.
		m_context = new hkpPhysicsContext();
		hkpPhysicsContext::registerAllPhysicsProcesses(); // all the physics viewers
		m_context->addWorld(world); // add the physics world so the viewers can see it
		m_contexts.pushBack(m_context);

		// Now we have finished modifying the world, release our write marker.
		world->unmarkForWrite();
	}

	m_vdb = new hkVisualDebugger(m_contexts);
	m_vdb->serve();
}

void PhysicsEngine::stepVisualDebugger() {
	m_context->syncTimers( m_threadPool );
	m_vdb->step();
}

void PhysicsEngine::shutdown() {
	if(m_vdb) {
		m_vdb->removeReference();
	}

	if(m_context) {
		m_context->removeReference();
	}

	// Contexts are not reference counted at the base class level by the VDB as
	// they are just interfaces really. So only delete the context after you have
	// finished using the VDB.
	
	delete m_jobQueue;

	//
	// Clean up the thread pool
	//

	m_threadPool->removeReference();
		
	#if defined HK_PLATFORM_PS3_PPU
		extern void quitSpurs( CellSpurs* spurs );
		quitSpurs( spurs );
	#endif

	hkBaseSystem::quit();
    hkMemoryInitUtil::quit();
	
	platformQuit();
}
*/